{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "mnist = tf.keras.datasets.mnist\n",
    "(train_images,train_labels),(test_images,test_labels) = mnist.load_data()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_images = train_images / 255.0\n",
    "test_images = test_images / 255.0\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(60000, 28, 28)"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_images.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_labels_ohe = tf.one_hot(train_labels,depth=10).numpy()\n",
    "test_labels_ohe = tf.one_hot(test_labels,depth = 10).numpy()\n",
    "\n",
    "myW = tf.Variable(np.zeros((784,64)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = tf.keras.models.Sequential()\n",
    "model.add(tf.keras.layers.Flatten(input_shape = (28, 28)))\n",
    "model.add(tf.keras.layers.Dense(units = 32 * 32, activation = \"relu\"))\n",
    "model.add(tf.keras.layers.Reshape((32, 32, 1)))\n",
    "model.add(tf.keras.layers.Conv2D(kernel_size = (5, 5),\n",
    "                                 padding = \"valid\",\n",
    "                                 filters = 6))\n",
    "model.add(tf.keras.layers.MaxPool2D())\n",
    "model.add(tf.keras.layers.Conv2D(kernel_size = (5, 5),\n",
    "                                 padding = \"valid\",\n",
    "                                 filters = 16))\n",
    "model.add(tf.keras.layers.MaxPool2D())\n",
    "model.add(tf.keras.layers.Conv2D(kernel_size = (5, 5),\n",
    "                                 padding = \"valid\",\n",
    "                                 filters = 120))\n",
    "model.add(tf.keras.layers.Reshape((120,)))\n",
    "model.add(tf.keras.layers.Dense(units = 64,activation = \"relu\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.add(tf.keras.layers.Dense(units = 32,kernel_initializer = \"normal\",activation = \"relu\"))\n",
    "model.add(tf.keras.layers.Dense(units = 10,activation = \"softmax\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model: \"sequential\"\n",
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "flatten (Flatten)            (None, 784)               0         \n",
      "_________________________________________________________________\n",
      "dense (Dense)                (None, 1024)              803840    \n",
      "_________________________________________________________________\n",
      "reshape (Reshape)            (None, 32, 32, 1)         0         \n",
      "_________________________________________________________________\n",
      "conv2d (Conv2D)              (None, 28, 28, 6)         156       \n",
      "_________________________________________________________________\n",
      "max_pooling2d (MaxPooling2D) (None, 14, 14, 6)         0         \n",
      "_________________________________________________________________\n",
      "conv2d_1 (Conv2D)            (None, 10, 10, 16)        2416      \n",
      "_________________________________________________________________\n",
      "max_pooling2d_1 (MaxPooling2 (None, 5, 5, 16)          0         \n",
      "_________________________________________________________________\n",
      "conv2d_2 (Conv2D)            (None, 1, 1, 120)         48120     \n",
      "_________________________________________________________________\n",
      "reshape_1 (Reshape)          (None, 120)               0         \n",
      "_________________________________________________________________\n",
      "dense_1 (Dense)              (None, 64)                7744      \n",
      "_________________________________________________________________\n",
      "dense_2 (Dense)              (None, 32)                2080      \n",
      "_________________________________________________________________\n",
      "dense_3 (Dense)              (None, 10)                330       \n",
      "=================================================================\n",
      "Total params: 864,686\n",
      "Trainable params: 864,686\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "model.summary()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.compile(optimizer=\"adam\",loss = \"categorical_crossentropy\",metrics=[\"accuracy\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_epochs = 20\n",
    "batch_size = 30\n",
    "callback = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/20\n",
      "1600/1600 - 9s - loss: 0.2900 - accuracy: 0.9105 - val_loss: 0.1228 - val_accuracy: 0.9638\n",
      "Epoch 2/20\n",
      "1600/1600 - 5s - loss: 0.1127 - accuracy: 0.9658 - val_loss: 0.1098 - val_accuracy: 0.9681\n",
      "Epoch 3/20\n",
      "1600/1600 - 5s - loss: 0.0848 - accuracy: 0.9740 - val_loss: 0.0988 - val_accuracy: 0.9719\n",
      "Epoch 4/20\n",
      "1600/1600 - 5s - loss: 0.0665 - accuracy: 0.9805 - val_loss: 0.0932 - val_accuracy: 0.9726\n",
      "Epoch 5/20\n",
      "1600/1600 - 5s - loss: 0.0583 - accuracy: 0.9826 - val_loss: 0.1141 - val_accuracy: 0.9670\n",
      "Epoch 6/20\n",
      "1600/1600 - 5s - loss: 0.0493 - accuracy: 0.9850 - val_loss: 0.1075 - val_accuracy: 0.9732\n",
      "Epoch 7/20\n",
      "1600/1600 - 5s - loss: 0.0475 - accuracy: 0.9858 - val_loss: 0.1013 - val_accuracy: 0.9740\n"
     ]
    }
   ],
   "source": [
    "train_history = model.fit(train_images,\n",
    "                          train_labels_ohe,\n",
    "                          validation_split=0.2,\n",
    "                          batch_size = batch_size,\n",
    "                          verbose = 2, \n",
    "                          epochs = train_epochs,\n",
    "                          callbacks = [callback])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(60000, 28, 28)"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_images.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.03405016, -0.02195158, -0.04635829, ..., -0.02477722,\n",
       "         0.01140734,  0.01134595],\n",
       "       [-0.03676685, -0.03929187,  0.04763685, ..., -0.010502  ,\n",
       "         0.01444069,  0.04512523],\n",
       "       [-0.04497131, -0.04026069, -0.05528198, ...,  0.03708265,\n",
       "        -0.05172972, -0.00794765],\n",
       "       ...,\n",
       "       [-0.03417937, -0.00344476,  0.05467038, ...,  0.03003987,\n",
       "        -0.02724943, -0.00073138],\n",
       "       [-0.05549766, -0.03035038, -0.02416052, ...,  0.01479145,\n",
       "         0.02138826, -0.02938827],\n",
       "       [-0.03431135, -0.04033509, -0.05044642, ..., -0.01776368,\n",
       "        -0.00386297,  0.01107161]], dtype=float32)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.trainable_variables[0].numpy()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
